libxl: Keyed unions key off an enum instead of an arbitrary expression
authorIan Campbell <ian.campbell@citrix.com>
Mon, 18 Jul 2011 13:52:30 +0000 (14:52 +0100)
committerIan Campbell <ian.campbell@citrix.com>
Mon, 18 Jul 2011 13:52:30 +0000 (14:52 +0100)
Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
Acked-by: Ian Jackson <ian.jackson.citrix.com>
Committed-by: Ian Jackson <ian.jackson.citrix.com>
tools/libxl/gentypes.py
tools/libxl/idl.txt
tools/libxl/libxl.idl
tools/libxl/libxltypes.py

index 120c6d357e5b2d521f0033f89a1ada66eecae7f5..23406fceac141efff7036bf86e0a614fec1942aa 100644 (file)
@@ -81,12 +81,13 @@ def libxl_C_type_destroy(ty, v, indent = "    ", parent = None):
     if isinstance(ty, libxltypes.KeyedUnion):
         if parent is None:
             raise Exception("KeyedUnion type must have a parent")
+        s += "switch (%s) {\n" % (parent + ty.keyvar_name)        
         for f in ty.fields:
             (nparent,fexpr) = ty.member(v, f, parent is None)
-            keyvar_expr = f.keyvar_expr % (parent + ty.keyvar_name)
-            s += "if (" + keyvar_expr + ") {\n"
+            s += "case %s:\n" % f.enumname
             s += libxl_C_type_destroy(f.type, fexpr, indent + "    ", nparent)
-            s += "}\n"
+            s += "    break;\n"
+        s += "}\n"
     elif isinstance(ty, libxltypes.Struct) and (parent is None or ty.destructor_fn is None):
         for f in [f for f in ty.fields if not f.const]:
             (nparent,fexpr) = ty.member(v, f, parent is None)
index dad59ac50c859f5cfe399c5c365582394253ad4a..271a2a8900c2dc315b96667f669811d7add5ce95 100644 (file)
@@ -127,13 +127,9 @@ libxltype.KeyedUnion
  upon another member in the containing type.
 
  The KeyedUnion.keyvar_name must contain the name of the member of the
- containing type which determines the valid member of the union
-
- The fields in a KeyedUnion have an extra Field.keyvar_expr
- property. This must be a string containing a single "%s" format
- specifier such that when "%s" is substited by an instance of
- KeyedUnion.keyvar_name it becomes a C expression which evaluates to
- True IFF this field currently contains valid data.
+ containing type which determines the valid member of the union. The
+ member referenced by KeyedUnion.keyvar_name has type
+ KeyedUnion.keyvar_type which must be an instance of the Enumeration type.
 
 Standard Types
 --------------
index 7f99f556f477d83af18fcf1fb2553764c743a802..f169c2c1296194bfeebe66851c135553ab217b87 100644 (file)
@@ -159,30 +159,28 @@ libxl_domain_build_info = Struct("domain_build_info",[
     ("disable_migrate", bool),
     ("cpuid",           libxl_cpuid_policy_list),
     ("type",            libxl_domain_type),
-    ("u", KeyedUnion(None, "type",
-                [("hvm", "%s == LIBXL_DOMAIN_TYPE_HVM", Struct(None,
-                                       [("firmware", string),
-                                        ("pae", bool),
-                                        ("apic", bool),
-                                        ("acpi", bool),
-                                        ("nx", bool),
-                                        ("viridian", bool),
-                                        ("timeoffset", string),
-                                        ("hpet", bool),
-                                        ("vpt_align", bool),
-                                        ("timer_mode", integer),
-                                        ("nested_hvm", bool),
-                                        ])),
-                 ("pv", "%s == LIBXL_DOMAIN_TYPE_PV", Struct(None,
-                                       [("kernel", libxl_file_reference),
-                                        ("slack_memkb", uint32),
-                                        ("bootloader", string),
-                                        ("bootloader_args", string),
-                                        ("cmdline", string),
-                                        ("ramdisk", libxl_file_reference),
-                                        ("features", string, True),
-                                        ("e820_host", bool, False, "Use host's E820 for PCI passthrough."),
-                                        ])),
+    ("u", KeyedUnion(None, libxl_domain_type, "type",
+                [("hvm", Struct(None, [("firmware", string),
+                                       ("pae", bool),
+                                       ("apic", bool),
+                                       ("acpi", bool),
+                                       ("nx", bool),
+                                       ("viridian", bool),
+                                       ("timeoffset", string),
+                                       ("hpet", bool),
+                                       ("vpt_align", bool),
+                                       ("timer_mode", integer),
+                                       ("nested_hvm", bool),
+                                       ])),
+                 ("pv", Struct(None, [("kernel", libxl_file_reference),
+                                      ("slack_memkb", uint32),
+                                      ("bootloader", string),
+                                      ("bootloader_args", string),
+                                      ("cmdline", string),
+                                      ("ramdisk", libxl_file_reference),
+                                      ("features", string, True),
+                                      ("e820_host", bool, False, "Use host's E820 for PCI passthrough."),
+                                      ])),
                  ])),
     ],
     comment =
index b7b46697dbabf17ce94e75cff0c69796dd9a6f9f..481e0d593e0dad56ee009ba94245a945ed3c8434 100644 (file)
@@ -116,6 +116,11 @@ class Enumeration(Type):
             self.values.append(EnumerationValue(self, num, name,
                                                 comment=comment,
                                                 typename=self.rawname))
+    def lookup(self, name):
+        for v in self.values:
+            if v.valuename == str.upper(name):
+                return v
+        return ValueError
         
 class Field(object):
     """An element of an Aggregate type"""
@@ -124,7 +129,7 @@ class Field(object):
         self.name = name
         self.const = kwargs.setdefault('const', False)
         self.comment = kwargs.setdefault('comment', None)
-        self.keyvar_expr = kwargs.setdefault('keyvar_expr', None)
+        self.enumname = kwargs.setdefault('enumname', None)
 
 class Aggregate(Type):
     """A type containing a collection of other types"""
@@ -181,18 +186,21 @@ class Union(Aggregate):
 
 class KeyedUnion(Aggregate):
     """A union which is keyed of another variable in the parent structure"""
-    def __init__(self, name, keyvar_name, fields, **kwargs):
+    def __init__(self, name, keyvar_type, keyvar_name, fields, **kwargs):
         Aggregate.__init__(self, "union", name, [], **kwargs)
 
+        if not isinstance(keyvar_type, Enumeration):
+            raise ValueError
+        
         self.keyvar_name = keyvar_name
+        self.keyvar_type = keyvar_type
 
         for f in fields:
-            # (name, keyvar_expr, type)
-
-            # keyvar_expr must contain exactly one %s which will be replaced with the keyvar_name
-
-            n, kve, ty = f
-            self.fields.append(Field(ty, n, keyvar_expr=kve))
+            # (name, enum, type)
+            e, ty = f
+            ev = keyvar_type.lookup(e)
+            en = ev.name
+            self.fields.append(Field(ty, e, enumname=en))
 
 #
 # Standard Types